package com.hazardousholdings.unkj.validation;

import java.util.ArrayList;
import java.util.List;

/**
 * CompositeValidator applies a number of Validators to a single input.
 */
public class CompositeValidator<T> implements Validator<T> {

	protected String invalidMessage;
	protected List<Validator<T>> validators;
	
	/**
	 * Instantiates a new composite validator.
	 * ValidationResults from this Validator will use 
	 * the invalid messages from the member Validators.
	 */
	public CompositeValidator() {
		this(null);
	}
	
	/**
	 * Instantiates a new composite validator.
	 * 
	 * @param invalidMessage the invalid message
	 */
	public CompositeValidator(String invalidMessage) {
		this.invalidMessage = invalidMessage;
		this.validators = new ArrayList<Validator<T>>();
	}
	
	@Override
	public String getInvalidMessage() {
		return invalidMessage;
	}

	@Override
	public void setInvalidMessage(String message) {
		this.invalidMessage = message;
	}

	/**
	 * Adds a Validator to the list of Validators that will be applied on validation.
	 * 
	 * @param validator the Validator to add
	 */
	public void addValidator(Validator<T> validator) {
		if(validator != null) {
			this.validators.add(validator);
		}
	}
	
	@Override
	public ValidationResults<T> validate(T input) {
		boolean compositeValid = true;
		T compositeResult = null;
		List<String> validationErrors = new ArrayList<String>(this.validators.size());
		
		for(Validator<T> validator : this.validators) {
			ValidationResults<T> result = validator.validate(input);
			
			compositeResult = result.getResult();
			if(!result.isValid()) {
				compositeValid = false;
				validationErrors.addAll(result.getMessages());
			}
		}
		
		if(compositeValid) {
			return new ValidationResults<T>(compositeResult, true);
		} else {
			if(this.getInvalidMessage() == null) {
				return new ValidationResults<T>(compositeResult, false, validationErrors);
			} else {
				return new ValidationResults<T>(compositeResult, false, this.getInvalidMessage());
			}
		}
		
	}

}
